/**
 * structure
 * 构造方法
 * 创建实例的时候，实际上是通过构造方法来初始化实例的。我们先来定义一个构造方法，能在创建Person实例的时候，一次性传入name和age，完成初始化
 * 
 * 默认构造方法:
 * 如果一个类没有定义构造方法，编译器会自动为我们生成一个默认构造方法，它没有参数，也没有执行语句
 * 要特别注意的是，如果我们自定义了一个构造方法，那么，编译器就不再自动创建默认构造方法
 */
public class structure {

    public static void main(String[] args) {
        Person xiaoming = new Person("xiaoMing", 18);
        System.out.println(xiaoming.getName());
        System.out.println(xiaoming.getAge());

        // 定义了两个构造方法,就可以分别调用带参数和不带参数的方法
        Person xiaowang = new Person();
        System.out.println("xiaowang.age:" + xiaowang.getAge());
        System.out.println("xiaowang.name:" + xiaowang.getName());

        Person1 xiaoZhang = new Person1("xiaoZhang", 18);
        System.out.println("xiaoZhang.name:" + xiaoZhang.name);//xiaoZhang
        System.out.println("xiaoZhang.age:" + xiaoZhang.age);//18

        Person2 xiaoZuo = new Person2();
        System.out.println("xiaoZuo.name:" + xiaoZuo.name);
        System.out.println("xiaoZuo.age" + xiaoZuo.age);
    }
}
class Person {
    private String name;
    private int age;

    // 由于构造方法是如此特殊，所以构造方法的名称就是类名。构造方法的参数没有限制，在方法内部，也可以编写任意语句。但是，和普通方法相比，构造方法没有返回值（也没有void），调用构造方法，必须用new操作符。
    public Person(String name,int age) {
        this.name = name;
        this.age = age;
    }

    // 如果既要能使用带参数的构造方法，又想保留不带参数的构造方法，那么只能把两个构造方法都定义出来：
    public Person() {
    }

    public String getName() {
        return this.name;
    }
    public int getAge(){
        return this.age;
    }
}

// 在定义类的属性的时候,可以直接进行初始化
// 在构造方法中还可以进行赋值
// 那么调用构造方法创建的实例,属性是什么?
// 实验过后,得知属性的值是构造方法中传入的值
// 因为类的构造先初始化字段,然后执行构造方法进行初始化,初始化方法后执行,所以字段的值等于勾走方法所传入的值
class Person1 {
    String name = "mingZi";
    int age = 0;

    public Person1(String name, int age){
        this.name = name;
        this.age = age;
    }
    public String getName() {
        return this.name;
    }
    public int getAge() {
        return this.age;
    }
}

// 可以定义多个构造方法,调用的时候,编译器会根据参数的个数自动分辨调用哪个构造方法
// 在构造方法中还可以调用其他的构造方法,调用其他构造方法的语法是this(...);
class Person2 {
    String name;
    int age;

    public Person2(String name, int age){
        this.name = name;
        this.age = age;
    }

    public Person2(String name){
        this(name, 18);
    }

    public Person2(){
        this("xiaoZuo");
    }
}

class Person3 {
    protected String name;
    protected int age;

    public Person3(String name, int age){
        this.name = name;
        this.age = age;
    }

    public Person3(String name){
        this(name, 18);
    }

    public Person3(){
        this("xiaoZuo");
    }
}